package com.imessage.service.impl;

import com.imessage.comm.Constants;
import com.imessage.service.BaseService;
import com.imessage.utils.SqlUtil;
import com.imessage.web.Page;
import com.opencsv.CSVReader;
import io.ebean.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.input.BOMInputStream;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class BaseServiceImpl implements BaseService {


    public <T> List<T> findList(Class<T> entityType, List<Expression> expressionList,String select, String orderby, int start,int length) {
        Query<T> query = Ebean.find(entityType);
        ExpressionList<T> tExpressionList = query.where();
        if(expressionList!=null
                &&expressionList.size()>0){
            for(Expression expression:expressionList){
                tExpressionList.add(expression);
            }
        }
        if(StringUtils.isNotBlank(orderby)){
            tExpressionList.order(orderby);
        }
        if(length>0){
            tExpressionList.setMaxRows(length);
        }
        if(StringUtils.isNotBlank(select)){
            tExpressionList.select(select);
        }
        return tExpressionList.setFirstRow(start).findList();
    }

    @Override
    public <T> List<T> findList(Class<T> entityType, List<Expression> expressionList, int start, int length) {
        return findList(entityType,expressionList,null,null,start,length);
    }

    @Override
    public <T> List<T> findList(Class<T> entityType, List<Expression> expressionList, String select, String orderby) {
        Query<T> query = Ebean.find(entityType);
        ExpressionList<T> tExpressionList = query.where();
        if(expressionList!=null
                &&expressionList.size()>0){
            for(Expression expression:expressionList){
                tExpressionList.add(expression);
            }
        }
        if(StringUtils.isNotBlank(orderby)){
            tExpressionList.order(orderby);
        }
        if(StringUtils.isNotBlank(select)){
            tExpressionList.select(select);
        }
        return tExpressionList.findList();
    }

    @Override
    public <T> List<T> findList(Class<T> entityType, List<Expression> expressionList) {
        return findList(entityType,expressionList,null, null);
    }

    @Override
    public <T> List<T> findList(Class<T> entityType, Expression expression, String select, String orderby) {
        Query<T> query = Ebean.find(entityType);
        ExpressionList<T> tExpressionList = query.where();
        if(expression!=null){
            tExpressionList.add(expression);
        }
        if(StringUtils.isNotBlank(orderby)){
            tExpressionList.order(orderby);
        }
        if(StringUtils.isNotBlank(select)){
            tExpressionList.select(select);
        }
        return tExpressionList.findList();
    }

    @Override
    public <T> List<T> findList(Class<T> entityType, Expression expression) {
        return findList(entityType, expression,  null,  null);
    }

    public <T> Page<T> findPage(Class<T> entityType, List<Expression> expressionList, String select, String orderby, int pageCurrent, int length) {
        Query<T> query = Ebean.find(entityType);
        ExpressionList<T> tExpressionList = query.where();
        if(expressionList!=null
                &&expressionList.size()>0){
            for(Expression expression:expressionList){
                tExpressionList.add(expression);
            }
        }
        int total=tExpressionList.findCount();
        if(StringUtils.isNotBlank(orderby)){
            tExpressionList.order(orderby);
        }
        if(StringUtils.isNotBlank(select)){
            tExpressionList.select(select);
        }
        List<T> list=tExpressionList.setFirstRow((pageCurrent-1)*length).setMaxRows(length).findList();
        return new Page<T>(list,pageCurrent,length,total);
    }

    @Override
    public <T> Page<T> findPage(Class<T> entityType, List<Expression> expressionList, int pageCurrent, int length) {
        return findPage(entityType, expressionList,null,  null,  pageCurrent, length);
    }

    public <T> T findObject(Class<T> entityType, Expression expression,String select,  String orderby){
        Query<T> query = Ebean.find(entityType);
        ExpressionList<T> tExpressionList = query.where();
        if(expression!=null){
            tExpressionList.add(expression);
        }
        if(StringUtils.isNotBlank(orderby)){
            tExpressionList.order(orderby);
        }
        if(StringUtils.isNotBlank(select)){
            tExpressionList.select(select);
        }
        return tExpressionList.setFirstRow(0).setMaxRows(1).findOne();
    }

    @Override
    public <T> T findObject(Class<T> entityType, Expression expression) {
        return findObject(entityType, expression,null,  null);
    }

    public <T> T findObject(Class<T> entityType, List<Expression> expressionList,String select, String orderby){
        Query<T> query = Ebean.find(entityType);
        ExpressionList<T> tExpressionList = query.where();
        if(expressionList!=null
                &&expressionList.size()>0){
            for(Expression expression:expressionList){
                tExpressionList.add(expression);
            }
        }
        if(StringUtils.isNotBlank(orderby)){
            tExpressionList.order(orderby);
        }
        if(StringUtils.isNotBlank(select)){
            tExpressionList.select(select);
        }
        return tExpressionList.setFirstRow(0).setMaxRows(1).findOne();
    }

    @Override
    public <T> T findObject(Class<T> entityType, List<Expression> expressionList) {
        return findObject(entityType, expressionList,null, null);
    }

    public <T> T findById(Class<T> entityType,Object id){
        if(id==null){
            return null;
        }
        return Ebean.find(entityType, id);
    }

    public <T> Query<T> createQuery(Class<T> entityType,List<Expression> expressionList,String select, String orderby){
        Query<T> query = Ebean.find(entityType);
        ExpressionList<T> tExpressionList = query.where();
        if(expressionList!=null
                &&expressionList.size()>0){
            for(Expression expression:expressionList){
                tExpressionList.add(expression);
            }
        }
        if(StringUtils.isNotBlank(orderby)){
            tExpressionList.order(orderby);
        }
        if(StringUtils.isNotBlank(select)){
            tExpressionList.select(select);
        }
        return tExpressionList.query();
    }

    @Override
    public <T> Query<T> createQuery(Class<T> entityType, List<Expression> expressionList) {
        return createQuery(entityType,expressionList,null, null);
    }

    public SqlQuery createSqlQuery(String sql){ return Ebean.createSqlQuery(sql);
    }

    @Override
    public int updateObject(Object o) {
        int state= Constants.STATE_OPERATOR_LOST;
        if(o==null){
            return Constants.STATE_OPERATOR_SUCC;
        }
        try{
            Ebean.update(o);
            state=Constants.STATE_OPERATOR_SUCC;
        }catch (Exception e){
            log.error("", e);
        }
       return state;
    }

    @Override
    public int saveObject(Object o) {
        int state= Constants.STATE_OPERATOR_LOST;
        if(o==null){
            return Constants.STATE_OPERATOR_SUCC;
        }
        try{
            Ebean.save(o);
            state=Constants.STATE_OPERATOR_SUCC;
        }catch (Exception e){
            log.error("", e);
        }
        return state;
    }

    @Override
    public int delObject(Object o) {
        int state= Constants.STATE_OPERATOR_LOST;
        if(o==null){
            return Constants.STATE_OPERATOR_SUCC;
        }
        try{
            Ebean.delete(o);
            state=Constants.STATE_OPERATOR_SUCC;
        }catch (Exception e){
            log.error("", e);
        }
        return state;
    }

    @Override
    public void close(Object o){
        if(o!=null){
            if(o instanceof CSVReader){
                try {
                    ((CSVReader)o).close();
                    o=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(o instanceof Reader){
                try {
                    ((Reader)o).close();
                    o=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(o instanceof FileInputStream){
                try {
                    ((FileInputStream)o).close();
                    o=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(o instanceof BOMInputStream){
                try {
                    ((BOMInputStream)o).close();
                    o=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void setSqlQuery(List<com.imessage.comm.Query> queryList, SqlQuery sqlQuery){
        for(com.imessage.comm.Query query:queryList){
            sqlQuery.setParameter(query.getName(), query.getValue());
        }
    }

    @Override
    public void setSqlRow(String key,SqlRow sqlRow,Map<String,Object[]> dbMap){
        Object o=sqlRow.get(key);
        if(o==null
                ||StringUtils.isBlank(o.toString())){
            return ;
        }
        String[] aliasAndColum=SqlUtil.getAliasAndColum(key);
        Object[] objs=dbMap.get(aliasAndColum[0]);
        if(objs==null){
            return ;
        }
        SqlUtil.setDbObject(
                (Class)objs[0],objs[1],
                SqlUtil.replaceAndfirstToUpper(aliasAndColum[1], "_", ""),o);
    }



}
